package k2kra;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class Server {
    private Vector<Socket> vs = new Vector<Socket>();
    private SimpleAccountBase sab = new SimpleAccountBase();
    private boolean running = true;

    public void start() {
        try {
            ServerSocket ss = new ServerSocket(5000);
            System.out.println("server is running...");
            while (running) {
                Socket sock = ss.accept();
                vs.add(sock);
                System.out.println("connected from " + sock.getRemoteSocketAddress());
                Thread t = new Handler(sock);
                t.start();
            }
            ss.close();
            sab.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(0);
        }
    }

    public void broadcast(String msg, Socket se) {
        for (Socket sock : vs) {
            if (se == sock)
                continue;
            try {
                BufferedWriter writer = new BufferedWriter(
                        new OutputStreamWriter(sock.getOutputStream(), StandardCharsets.UTF_8));
                writer.write(msg + "\n");
                writer.flush();
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }

    public static void main(String[] args) {
        Server sv = new Server();
        System.out.println(sv.sab.displayAll());
        sv.start();
    }

    class Handler extends Thread {
        Socket sock;
        String user_name = "";
        BufferedWriter writer;
        BufferedReader reader;

        public Handler(Socket sock) {
            this.sock = sock;
        }

        @Override
        public void run() {
            try (InputStream input = this.sock.getInputStream()) {
                try (OutputStream output = this.sock.getOutputStream()) {
                    handle(input, output);
                }
            } catch (Exception e) {
                try {
                    this.sock.close();
                    vs.remove(sock);
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                    System.exit(0);
                }
                System.out.println(sock.getRemoteSocketAddress() + " disconnected.");
            }
        }

        private void sendMsg(String msg) {
            try {
                writer.write(msg + "\n");
                writer.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void parseMsg(String s) throws Exception {
            if (s.startsWith("\\leave")) {
                if (!user_name.equals("")) {
                    user_name = "";
                    return;
                }
                sendMsg("[server]sign in first.");
            } else
            if (s.startsWith("\\login")) {
                if (!user_name.equals("")) {
                    sendMsg("[server]sign out first.");
                    return;
                }
                boolean flag = false;
                String[] results = s.split(" ");
                if (results.length > 2) {
                    String user_name = results[1];
                    String password = results[2];
                    if (sab.signIn(user_name, password)) {
                        broadcast("[server] " + user_name + " has connected.", null);
                        this.user_name = user_name;
                        flag = true;
                    } else {
                        sendMsg("0[server]incorrect username or password .");
                    }
                } else {
                    sendMsg("0[server]format error");
                }
                if (flag) {
                    System.out.println("signin success\n");
                } else {
                    System.out.println("signin failure\n");
                }
            } else
            if (s.startsWith("\\register")) {
                if (!user_name.equals("")) {
                    sendMsg("[server]sign out first.");
                    return;
                }
                boolean flag = false;
                String[] results = s.split(" ");
                if (results.length > 2) {
                    String user_name = results[1];
                    String password = results[2];
                    if (sab.signUp(user_name, password)) {
                        broadcast("[server]" + user_name + " has connected.", null);
                        this.user_name = user_name;
                        flag = true;
                    } else {
                        sendMsg("0[server]invalid account.");
                    }
                } else {
                    sendMsg("0[server]format error.");
                }
                if (flag) {
                    System.out.println("registration success\n");
                } else {
                    System.out.println("registration failure\n");
                }
            } else
            //管理员账户可以关闭服务器
            if (s.startsWith("\\shutdown")) {
                if (!user_name.equals("admin@test.com")) {
                    sendMsg("[server]permission denied.");
                    return;
                }
                sab.close();
                System.exit(0);
            } else
            if (s.startsWith("\\peel")) {
                if (!user_name.equals("admin@test.com")) {
                    sendMsg("[server]permission denied.");
                    return;
                }
                sendMsg("[server]"+sab.displayAll());
            } else
            if (!user_name.equals("")) {
                broadcast("["+user_name+"] "+s, sock);
            } else {
                sendMsg("[server]you should sign in or sign up first.");
            }
        }

        private void handle(InputStream input, OutputStream output) throws Exception {
            writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
            reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
            sendMsg("[server]hello, visitor.");
            while ( true ) {
                String s = reader.readLine();
                System.out.println("[" + sock.getRemoteSocketAddress() + "] " + s);
                parseMsg(s);
            }
        }
    }
}